--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tests/backend/test_rrc_api_security.py ec74a2651e897325b14269ae52d11b1e12f0b6e2 (ec74a265) Text, 11.55 KB
T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""Security and fuzz tests for Reticulum Relay Chat HTTP API endpoints."""
Tff7b72import T7ee787json
Tff7b72import T7ee787os
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3MagicMock
Tff7b72import T7ee787pytest
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3HealthCheckTb4b4b4, Te6edf3givenTb4b4b4, Te6edf3settings
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3strategies Tff7b72as Te6edf3st
Te6edf3HUB_HASH_HEX Tff7b72= Ta5d6ff"Ta5d6ff00112233445566778899aabbccddeeffTa5d6ff"
Tff7b72def Td2a8ff_find_handlerTb4b4b4(Te6edf3appTb4b4b4, Te6edf3pathTb4b4b4, Te6edf3methodTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3route Tff7b72in Te6edf3appTff7b72.Td2a8ffget_routesTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3routeTff7b72.Td2a8ffpath Tff7b72== Te6edf3path Tff7b72and Te6edf3routeTff7b72.Td2a8ffmethod Tff7b72== Te6edf3methodTb4b4b4:
Tff7b72return Te6edf3routeTff7b72.Td2a8ffhandler
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tff7b72NoneTb4b4b4, Te6edf3match_infoTff7b72=Tff7b72NoneTb4b4b4, Te6edf3queryTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Te6edf3request Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ff_jsonTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3json_body Tff7b72if Te6edf3json_body Tff7b72is Tff7b72not Tff7b72None Tff7b72else Tb4b4b4{Tb4b4b4}
Te6edf3requestTff7b72.Td2a8ffjson Tff7b72= Te6edf3_json
Te6edf3requestTff7b72.Td2a8ffmatch_info Tff7b72= Te6edf3match_info Tff7b72or Tb4b4b4{Tb4b4b4}
Te6edf3requestTff7b72.Td2a8ffquery Tff7b72= Te6edf3query Tff7b72or Tb4b4b4{Tb4b4b4}
Tff7b72return Te6edf3request
Tff7b72async Tff7b72def Td2a8ff_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3hub_hash_hexTff7b72=Te6edf3HUB_HASH_HEXTb4b4b4)Tb4b4b4:
Te6edf3post Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Tff7b72return Tff7b72await Te6edf3postTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3hub_hash_hexTb4b4b4}Tb4b4b4)Tb4b4b4)
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_api_unavailable_returns_503Tb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3mock_appTff7b72.Td2a8ffrrc_manager Tff7b72= Tff7b72None
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffGETTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff503
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_server_api_unavailable_returns_503Tb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3mock_appTff7b72.Td2a8ffrrc_server_manager Tff7b72= Tff7b72None
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/serversTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffGETTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff503
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_add_hub_rejects_path_traversal_hashTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3post Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3traversal Tff7b72= Ta5d6ff"Ta5d6ff../Ta5d6ff" Tff7b72+ Te6edf3HUB_HASH_HEX
Te6edf3response Tff7b72= Tff7b72await Te6edf3postTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3traversalTb4b4b4}Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_add_hub_rejects_sql_injection_shaped_hashTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3post Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3postTb4b4b4(
Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff'Ta5d6ff; DROP TABLE hubs; --Ta5d6ff" Tff7b72+ Ta5d6ff"Ta5d6ffaaTa5d6ff" Tff7b72* T79c0ff8Tb4b4b4}Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_add_hub_rejects_null_and_control_bytesTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3post Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3dirty Tff7b72= Te6edf3HUB_HASH_HEXTb4b4b4[Tb4b4b4:T79c0ff8Tb4b4b4] Tff7b72+ Ta5d6ff"Tffea00\x00Tffea00\x01Ta5d6ff" Tff7b72+ Te6edf3HUB_HASH_HEXTb4b4b4[T79c0ff10Tb4b4b4:Tb4b4b4]
Te6edf3response Tff7b72= Tff7b72await Te6edf3postTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3dirtyTb4b4b4}Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_operations_on_unknown_hub_return_404Tb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4)
Te6edf3unknown Tff7b72= Ta5d6ff"Ta5d6ffffTa5d6ff" Tff7b72* T79c0ff16
Te6edf3handlers Tff7b72= Tb4b4b4[
Tb4b4b4(Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffDELETETa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4(Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/connectTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4(
Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/rooms/Tffd700{room}Ta5d6ff/messagesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffGETTa5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4]
Tff7b72for Te6edf3pathTb4b4b4, Te6edf3method Tff7b72in Te6edf3handlersTb4b4b4:
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3pathTb4b4b4, Te6edf3methodTb4b4b4)
Tff7b72assert Te6edf3handler Tff7b72is Tff7b72not Tff7b72None
Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(
Te6edf3_make_requestTb4b4b4(Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3unknownTb4b4b4, Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff404
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_join_room_traversal_name_history_stays_in_storageTb4b4b4(
Te6edf3mock_appTb4b4b4,
Te6edf3tmp_pathTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4)
Te6edf3manager Tff7b72= Te6edf3mock_appTff7b72.Td2a8ffrrc_manager
Te6edf3hub Tff7b72= Te6edf3managerTff7b72.Td2a8fffind_hub_by_hexTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4)
Te6edf3join Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3joinTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff../../etc/passwdTa5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3managerTff7b72.Td2a8ffstorage_dirTb4b4b4)
Te6edf3hist_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3managerTff7b72.Td2a8ff_history_pathTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6ff../../etc/passwdTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3hist_pathTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3root Tff7b72+ Te6edf3osTff7b72.Td2a8ffsepTb4b4b4)
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_send_message_rejects_non_string_textTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4)
Te6edf3join Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Tff7b72await Te6edf3joinTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3send Tff7b72= Te6edf3_find_handlerTb4b4b4(
Te6edf3mock_appTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/rooms/Tffd700{room}Ta5d6ff/messagesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72for Te6edf3bad_text Tff7b72in Tb4b4b4[Tff7b72NoneTb4b4b4, T79c0ff12345Tb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6ffxTa5d6ff"Tb4b4b4: T79c0ff1Tb4b4b4}Tb4b4b4, Tb4b4b4[Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4]Tb4b4b4]Tb4b4b4:
Te6edf3response Tff7b72= Tff7b72await Te6edf3sendTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4: Te6edf3bad_textTb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72in Tb4b4b4(T79c0ff400Tb4b4b4, T79c0ff500Tb4b4b4)
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_send_message_rejects_empty_textTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4)
Te6edf3join Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Tff7b72await Te6edf3joinTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3send Tff7b72= Te6edf3_find_handlerTb4b4b4(
Te6edf3mock_appTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/rooms/Tffd700{room}Ta5d6ff/messagesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3sendTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_reorder_rejects_non_listTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4)
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/orderTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPUTTa5d6ff"Tb4b4b4)
Tff7b72for Te6edf3bad Tff7b72in Tb4b4b4[Ta5d6ff"Ta5d6ffnot-a-listTa5d6ff"Tb4b4b4, T79c0ff42Tb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6ffhubTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4]Tb4b4b4:
Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashesTa5d6ff"Tb4b4b4: Te6edf3badTb4b4b4}Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_reorder_ignores_unknown_hashes_without_errorTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4)
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/orderTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPUTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(
Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashesTa5d6ff"Tb4b4b4: Tb4b4b4[Ta5d6ff"Ta5d6ffdeadbeefTa5d6ff" Tff7b72* T79c0ff4Tb4b4b4]Tb4b4b4}Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Tff7b72assert Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffhubsTa5d6ff"Tb4b4b4]Tb4b4b4) Tff7b72== T79c0ff1
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_server_create_room_rejects_empty_nameTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3post Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/serversTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3created Tff7b72= Tff7b72await Te6edf3postTb4b4b4(
Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHost HubTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4}Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3hub_id Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3createdTff7b72.Td2a8ffbodyTb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffhubTa5d6ff"Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4]
Te6edf3create_room Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/servers/Tffd700{hub_id}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3create_roomTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_idTa5d6ff"Tb4b4b4: Te6edf3hub_idTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_server_delete_unknown_hub_returns_404Tb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/servers/Tffd700{hub_id}Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffDELETETa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(
Te6edf3_make_requestTb4b4b4(Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_idTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffnonexistentTa5d6ff" Tff7b72* T79c0ff4Tb4b4b4}Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff404
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_messages_encoded_room_history_stays_in_storageTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4)
Te6edf3manager Tff7b72= Te6edf3mock_appTff7b72.Td2a8ffrrc_manager
Te6edf3hub Tff7b72= Te6edf3managerTff7b72.Td2a8fffind_hub_by_hexTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4)
Te6edf3room Tff7b72= Ta5d6ff"Ta5d6ff..Tffd700%2FTa5d6ff..Tffd700%2FTa5d6ffsecretTa5d6ff"
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(
Te6edf3mock_appTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/rooms/Tffd700{room}Ta5d6ff/messagesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffGETTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3match_infoTff7b72=Tb4b4b4{
Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4,
Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Te6edf3roomTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3managerTff7b72.Td2a8ffstorage_dirTb4b4b4)
Te6edf3hist_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3managerTff7b72.Td2a8ff_history_pathTb4b4b4(Te6edf3hubTb4b4b4, Te6edf3roomTb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3hist_pathTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3root Tff7b72+ Te6edf3osTff7b72.Td2a8ffsepTb4b4b4)
Tf0883e@givenTb4b4b4(
Te6edf3hub_hashTff7b72=Te6edf3stTff7b72.Td2a8ffone_ofTb4b4b4(
Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3min_sizeTff7b72=T79c0ff0Tb4b4b4, Te6edf3max_sizeTff7b72=T79c0ff64Tb4b4b4)Tb4b4b4,
Te6edf3stTff7b72.Td2a8ffbinaryTb4b4b4(Te6edf3min_sizeTff7b72=T79c0ff0Tb4b4b4, Te6edf3max_sizeTff7b72=T79c0ff32Tb4b4b4)Tff7b72.Td2a8ffmapTb4b4b4(Tff7b72lambda Te6edf3bTb4b4b4: Te6edf3bTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tf0883e@settingsTb4b4b4(
Te6edf3max_examplesTff7b72=T79c0ff80Tb4b4b4,
Te6edf3deadlineTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3suppress_health_checkTff7b72=Tb4b4b4[Te6edf3HealthCheckTff7b72.Td2a8fffunction_scoped_fixtureTb4b4b4]Tb4b4b4,
Tb4b4b4)
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_add_hub_fuzz_invalid_hashes_never_500Tb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3hub_hashTb4b4b4)Tb4b4b4:
Te6edf3post Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3postTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3hub_hashTb4b4b4}Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72in Tb4b4b4(T79c0ff200Tb4b4b4, T79c0ff400Tb4b4b4)
Tff7b72if Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200Tb4b4b4:
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Tff7b72assert Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffhubTa5d6ff"Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4]Tb4b4b4) Tff7b72== Te6edf3HUB_HASH_HEXTff7b72.Td2a8ff__len__Tb4b4b4(Tb4b4b4)
Tf0883e@givenTb4b4b4(Te6edf3roomTff7b72=Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3max_sizeTff7b72=T79c0ff128Tb4b4b4)Tb4b4b4)
Tf0883e@settingsTb4b4b4(
Te6edf3max_examplesTff7b72=T79c0ff60Tb4b4b4,
Te6edf3deadlineTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3suppress_health_checkTff7b72=Tb4b4b4[Te6edf3HealthCheckTff7b72.Td2a8fffunction_scoped_fixtureTb4b4b4]Tb4b4b4,
Tb4b4b4)
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_join_room_fuzz_never_500Tb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3roomTb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4)
Te6edf3join Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3joinTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Te6edf3roomTb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72in Tb4b4b4(T79c0ff200Tb4b4b4, T79c0ff400Tb4b4b4)
Tf0883e@givenTb4b4b4(
Te6edf3textTff7b72=Te6edf3stTff7b72.Td2a8ffone_ofTb4b4b4(
Te6edf3stTff7b72.Td2a8ffnoneTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3max_sizeTff7b72=T79c0ff2048Tb4b4b4)Tb4b4b4,
Te6edf3stTff7b72.Td2a8ffbinaryTb4b4b4(Te6edf3min_sizeTff7b72=T79c0ff0Tb4b4b4, Te6edf3max_sizeTff7b72=T79c0ff256Tb4b4b4)Tff7b72.Td2a8ffmapTb4b4b4(
Tff7b72lambda Te6edf3bTb4b4b4: Te6edf3bTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffsurrogateescapeTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tf0883e@settingsTb4b4b4(
Te6edf3max_examplesTff7b72=T79c0ff60Tb4b4b4,
Te6edf3deadlineTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3suppress_health_checkTff7b72=Tb4b4b4[Te6edf3HealthCheckTff7b72.Td2a8fffunction_scoped_fixtureTb4b4b4]Tb4b4b4,
Tb4b4b4)
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_send_message_fuzz_never_500_when_disconnectedTb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3textTb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3_add_hubTb4b4b4(Te6edf3mock_appTb4b4b4)
Te6edf3join Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Tff7b72await Te6edf3joinTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3send Tff7b72= Te6edf3_find_handlerTb4b4b4(
Te6edf3mock_appTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/rooms/Tffd700{room}Ta5d6ff/messagesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3sendTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4: Te6edf3textTb4b4b4, Ta5d6ff"Ta5d6ffactionTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72in Tb4b4b4(T79c0ff400Tb4b4b4, T79c0ff500Tb4b4b4)
Tf0883e@givenTb4b4b4(
Te6edf3nameTff7b72=Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3max_sizeTff7b72=T79c0ff256Tb4b4b4)Tb4b4b4,
Te6edf3greetingTff7b72=Te6edf3stTff7b72.Td2a8ffone_ofTb4b4b4(Te6edf3stTff7b72.Td2a8ffnoneTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3max_sizeTff7b72=T79c0ff512Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tf0883e@settingsTb4b4b4(
Te6edf3max_examplesTff7b72=T79c0ff40Tb4b4b4,
Te6edf3deadlineTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3suppress_health_checkTff7b72=Tb4b4b4[Te6edf3HealthCheckTff7b72.Td2a8fffunction_scoped_fixtureTb4b4b4]Tb4b4b4,
Tb4b4b4)
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rrc_server_create_hub_fuzz_never_500Tb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3greetingTb4b4b4)Tb4b4b4:
Te6edf3post Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/serversTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3postTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3nameTb4b4b4,
Ta5d6ff"Ta5d6ffgreetingTa5d6ff"Tb4b4b4: Te6edf3greetingTb4b4b4,
Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Tff7b72assert Ta5d6ff"Ta5d6ffhubTa5d6ff" Tff7b72in Te6edf3data
Tff7b72def Td2a8fftest_rrc_history_files_remain_under_storageTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787rrc Tff7b72import Te6edf3protocol Tff7b72as Te6edf3proto
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787rrcT7ee787.T7ee787manager Tff7b72import Te6edf3RRCManager
Tff7b72class T56d364IdTb4b4b4:
Tffa657hash Tff7b72= Tffa657bytesTb4b4b4(Tffa657rangeTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4)
Te6edf3manager Tff7b72= Te6edf3RRCManagerTb4b4b4(Te6edf3identityTff7b72=Te6edf3IdTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3storage_dirTff7b72=Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4)
Te6edf3hub Tff7b72= Te6edf3managerTff7b72.Td2a8ffadd_hubTb4b4b4(Tffa657bytesTb4b4b4(Tffa657rangeTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3room Tff7b72in Tb4b4b4[Ta5d6ff"Ta5d6ff../xTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffaTa5d6ff" Tff7b72* T79c0ff100Tb4b4b4, Ta5d6ff"Ta5d6ffroom/with/slashTa5d6ff"Tb4b4b4]Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3normalized Tff7b72= Te6edf3protoTff7b72.Td2a8ffnormalize_roomTb4b4b4(Te6edf3roomTb4b4b4)
Te6edf3hubTff7b72.Td2a8ffadd_roomTb4b4b4(Te6edf3normalizedTb4b4b4)
Te6edf3msg Tff7b72= Te6edf3protoTff7b72.Td2a8ffRRCMessageTb4b4b4(Ta5d6ff"Ta5d6ffmsgTa5d6ff"Tb4b4b4, Te6edf3normalizedTb4b4b4, Ta5d6ffbTa5d6ff"Tffea00\x01Ta5d6ff" Tff7b72* T79c0ff16Tb4b4b4, Ta5d6ff"Ta5d6ffnTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftTa5d6ff"Tb4b4b4, T79c0ff1Tb4b4b4)
Te6edf3hubTff7b72.Td2a8ff_record_messageTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72continue
Te6edf3root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3tmp_pathTb4b4b4)
Tff7b72for Te6edf3dirpathTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3filenames Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3fn Tff7b72in Te6edf3filenamesTb4b4b4:
Te6edf3path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3dirpathTb4b4b4, Te6edf3fnTb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3pathTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3rootTb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────